using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.IO.Ports;
using Peak.Can.Basic;
using System.Security.Cryptography;
using System.Net.NetworkInformation;
using TPCANHandle = System.Byte;


namespace WinCANTool
{
    public partial class FlashWindow1319 : Form
    {
        public const int BUFFER_SIZE              = 200;

        private new MDIWindow ParentForm;
        private string CurrentPath = "";
        private string OSFileName;
        private string MainNodeIDCurrent;
		private const string secu_secret = "LindeOS,.12";

        private delegate void SetDoneBox(bool ON_Off);
        private delegate void GetSegmentDone(int OpArg);
        private delegate void GetTickDone(object sender, EventArgs e);
		private delegate void GetKwpDone(object sender, EventArgs e);


        public Thread m_thread;
        public Thread mdi_thread;
        public Thread f_thread;
		public Thread f_kwpthread;
        public Thread prof_thread;

        public struct MsgIn
        {
            public TPCANTimestamp RcvTimeRx;
            public TPCANMsg msgInRx;
            public bool DisplayDone;
        }		

        private bool m_fThreadTerminated = true;
        private bool mdi_fThreadTerminated = true;
        private bool f_fThreadTerminated = true;
		private bool f_fKwpThreadTerminated = true;
        private bool prof_fThreadTerminated = true;
        private bool tx_ThreadTerminated = true;
        private TPCANHandle m_hClient = 0;
		private SerialPort m_hSerialPort;
        private byte m_hNet = 0;
        private byte m_hHw = 0;
        private AutoResetEvent m_RcvEvent = new System.Threading.AutoResetEvent(false);
        public bool LockDisplay = false;
        public bool OverFlowFault = false;

        public TPCANTimestamp tstamp = new TPCANTimestamp();
        private TPCANMsg ReceiveBufferHW = new TPCANMsg();

        //private int StartIndex = 0;
        private int EndIndex = 0;
        private int NextIndex = 0;

        public bool DelayON = true;
        public uint TxDelayMilli = 0;
		public uint kwp_object = 0;

        //public CycleTxThread TxCycleClass;
        //public Thread Cycle_tx_thread;
        //private bool CycleThreadOn = false;



        MsgIn[] SDOMsgInMDI = new MsgIn[BUFFER_SIZE];
        private CanToolOptionData CanDisplayOptions;
        private ParseSymbols MsgSymbols = new ParseSymbols();

        private CreateSymbolString NewSymString = new CreateSymbolString();
        private CreateRawMsgString NewRawString = new CreateRawMsgString();
        private long StartTimeTicks;
#if DEBUG
        private string FileNameLog = Directory.GetCurrentDirectory() + @"\Shuaru.txt";
        private FileStream fslog;
        StreamWriter newfilelog;
#endif


        public FlashWindow1319(MDIWindow ParentF, CanToolOptionData Options)
        {
            InitializeComponent();
            ParentForm = ParentF;
            MsgSymbols = ParentForm.CurrentSymbols;

            StartTimeTicks = ParentForm.StartTime;
            NewSymString.SetTime(StartTimeTicks);
            NewRawString.SetTime(StartTimeTicks);
            FactoryUserInit(true);
            CanDisplayOptions = Options;
			serial_number = CanDisplayOptions.serial_number;
			security_key = CanDisplayOptions.security_key;
			textSN.Text = serial_number;
            textValidateKey.Text = security_key;
			
            TickDone += new EventHandler(OsTickDone);
			KwpDone += new EventHandler(OSKwpDone);
            ClearEvents();
            FlashOpDone += new MessageOpHandler(OsFlashDone);	
			
            GetMainFlashFile();
            GetNodeIDs();
            Fragment = new byte[7];
            CanMessageOut.DATA = new byte[8];
            CanMessageIn.DATA = new byte[8];
#if DEBUG
            fslog = new FileStream(FileNameLog, FileMode.Open, FileAccess.Write);
            newfilelog = new StreamWriter(fslog);
#endif
            
        }

        private void GetNodeIDs()
        {
            MainNodeIDCurrent = ParentForm.GetMainNodeID();
            NodeIdTextBox.Text = MainNodeIDCurrent;
			UpdateNodeId();
        }
        
        private void GetMainFlashFile()
        {
            OSFileName = ParentForm.GetOSFileName();
            string[] pathname = OSFileName.Split(new Char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
            osFileName.Text = "";
            for (int i = 0; (i < (pathname.Length - 1)); i++)
            {
                osFileName.Text += pathname[i] + '\\';
            }
            MainFileName.Text = pathname[pathname.Length - 1];


        }
        private void BrowseOsFile_Click(object sender, EventArgs e)
        {
            openFileDialog1.InitialDirectory = CurrentPath + @"\Symbols";
            openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.FileName = "";
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                OSFileName = openFileDialog1.FileName;
                ParentForm.SetOSFileName(OSFileName);
                //SaveNodeInfo();
                GetMainFlashFile();  
            }
        }

        
        private void BrowseAppFile_Click(object sender, EventArgs e)
        {
            openFileDialog1.InitialDirectory = CurrentPath + @"\Symbols";
            openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.FileName = "";
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
            }

        }

        private void StartOsFlash_Click(object sender, EventArgs e)
        {

            int ObjectIndex = 0, FileObjectIndex = 0;

            SaveNodeInfo();

            if (NodeIdTextBox.Text != "")
            {
                int Node = Int16.Parse(NodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);

                ParentForm.newMDIChild1.AbortFlashThread();
                if (ObjectIndexTextBox.Text != "")
                    ObjectIndex = Int32.Parse(ObjectIndexTextBox.Text, System.Globalization.NumberStyles.HexNumber);

                if (FileObjectTextBox.Text != "")
                    FileObjectIndex = Int32.Parse(FileObjectTextBox.Text, System.Globalization.NumberStyles.HexNumber);

                int FlashKey = Int32.Parse(FlashKeyTextBox.Text, System.Globalization.NumberStyles.HexNumber);

                if (SecondChannelON.Checked)
                {
                    ParentForm.newMDIChild1.TxNodeId = uint.Parse(TxNodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                    ParentForm.newMDIChild1.RxNodeId = uint.Parse(RxNodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                    ParentForm.newMDIChild1.UseSecondChannel = true;
                }
                else
                    ParentForm.newMDIChild1.UseSecondChannel = false;

                OsDonecheckBox.Enabled = true;
                OsDonecheckBox.Checked = false;

                FlashFailBox.Enabled = true;
				FlashFailBox.Checked = false;   
#if DEBUG
                fslog.Seek(0, SeekOrigin.Begin);  
                fslog.SetLength(0);
                newfilelog.Close();
                fslog.Close();


                fslog = new FileStream(FileNameLog, FileMode.Append, FileAccess.Write);
                newfilelog = new StreamWriter(fslog);
#endif

				
                ParentForm.newMDIChild1.NodeId = Node;
                ParentForm.newMDIChild1.FileInName = OSFileName;
                ParentForm.newMDIChild1.FlashKeyIn = FlashKey;
                ParentForm.newMDIChild1.FileObjectIndex = FileObjectIndex;
                ParentForm.newMDIChild1.CommandObjectIndex = ObjectIndex;
                ParentForm.newMDIChild1.StartFlashThread();

				can_tx_textBox.Text="";

                ProgramProgressBar.Value = 0;
            }
            else
                MessageBox.Show("Incorrect Node ID");

        }



        private void StartAppFlash_Click(object sender, EventArgs e)
        {
            int ObjectIndex = 0, FileObjectIndex = 0;

            SaveNodeInfo();

            if (SupNodeIdTextBox.Text != "")
            {
                int Node = Int16.Parse(SupNodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);

                ParentForm.newMDIChild1.AbortFlashThread();
                if (ObjectIndexTextBox.Text != "")
                    ObjectIndex = Int32.Parse(ObjectIndexTextBox.Text, System.Globalization.NumberStyles.HexNumber);

                if (FileObjectTextBox.Text != "")
                    FileObjectIndex = Int32.Parse(FileObjectTextBox.Text, System.Globalization.NumberStyles.HexNumber);

                int FlashKey = Int32.Parse(FlashKeyTextBox.Text, System.Globalization.NumberStyles.HexNumber);


                OsDonecheckBox.Enabled = true;
                OsDonecheckBox.Checked = false;
                ParentForm.newMDIChild1.NodeId = Node;

                ParentForm.newMDIChild1.FlashKeyIn = FlashKey;
                ParentForm.newMDIChild1.FileObjectIndex = FileObjectIndex;
                ParentForm.newMDIChild1.CommandObjectIndex = ObjectIndex;
                ParentForm.newMDIChild1.StartFlashThread();

                ProgramProgressBar.Value = 0;

            }
            else
                MessageBox.Show("Incorrect Node ID");

        }

        public void OsTickDone(object sender, EventArgs e)
        {

            if (this.ProgramProgressBar.InvokeRequired)
            {
                GetTickDone d = new GetTickDone(OsTickDone);
                this.Invoke(d, new object[] { sender, e });
            }
            else
            {
                ProgramProgressBar.Maximum = ParentForm.newMDIChild1.FullBlockCount;
				if(ParentForm.newMDIChild1.init_value == 0)
				{
					ProgramProgressBar.Value = 0;
					ParentForm.newMDIChild1.init_value = 0xff;
				}
                if (ProgramProgressBar.Value < ProgramProgressBar.Maximum)
                    ProgramProgressBar.Value += 1;
            }

        }

        public void OSKwpDone(object sender, EventArgs e)
        {

            if (this.textSN.InvokeRequired)
            {
                GetKwpDone d = new GetKwpDone(OSKwpDone);
                this.Invoke(d, new object[] { sender, e });
            }
            else
            {
                textSN.Text = serial_number;
				ParentForm.SetSN(textSN.Text); 
            }
        }
		

        public void EnableStartFlashButton()
		{
			StartOsFlash.Enabled = true;
		}
		public void DisableStartFlashButton()
		{
            StartOsFlash.Enabled = false;
		}

        public void EnableReadSNButton()
		{
			buttonReadSN.Enabled = true;
		}
		public void DisableReadSNButton()
		{
            buttonReadSN.Enabled = false;
		}


        public void EnableValidateButton()
		{
			buttonValidate.Enabled = true;
		}
		public void DisableValidateButton()
		{
            buttonValidate.Enabled = false;
		}		
		

        public void OsFlashDone(object sender, MessageOpArgs e)
        {
            if ((ParentForm.newMDIChild1.FlashOpOn) || (e.ReturnOpValue != 0))
            {
                ParentForm.newMDIChild1.FlashOpOn = false;
                ShowDone(false);
                ShowFail(true);
                if (e.ReturnOpValue == -99)
                   ShowString(e.ReturnOpValue);            
            }
            
            else
            {
                if ((!ParentForm.newMDIChild1.SegmentWrite) && (!ParentForm.newMDIChild1.ValueWrite))
                    ShowString(0);

                ShowDone(true);
                ShowFail(false);

            }
#if DEBUG

            newfilelog.Close();
            fslog.Close();
#endif
            ParentForm.newMDIChild1.FlashOpOn = false;
            ParentForm.newMDIChild1.AbortFlashThread();
        }


        public void ShowDone(bool DoneON)
        {


            if (this.OsDonecheckBox.InvokeRequired)
            {
                SetDoneBox d = new SetDoneBox(ShowDone);
                this.Invoke(d, new object[] { DoneON });
            }
            else
            {
                OsDonecheckBox.Enabled = DoneON;
                OsDonecheckBox.Checked = DoneON;

            }
        }

        public void ShowFail(bool DoneON)
        {


            if (this.FlashFailBox.InvokeRequired)
            {
                SetDoneBox d = new SetDoneBox(ShowFail);
                this.Invoke(d, new object[] { DoneON });
            }
            else
            {
                FlashFailBox.Enabled = DoneON;
                FlashFailBox.Checked = DoneON;

            }
        }



        public void ShowString(int StringArg)
        {


            if (this.SegmentString.InvokeRequired)
            {
                GetSegmentDone d = new GetSegmentDone(ShowString);
                this.SegmentString.Invoke(d, new object[] { StringArg });
            }
            else
            {
                if (StringArg == 0)
                    SegmentString.Text = ParentForm.newMDIChild1.StringData1;
                else if (StringArg == -99)
                    SegmentString.Text = "Abort Message";

            }
        }


        private void FlashWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
        	
            ParentForm.newMDIChild1.FlashOpOn = false;
            StopInhibit();
            ParentForm.newMDIChild1.AbortFlashThread();
            ParentForm.newMDIChild1.AbortKWPThread();
			
            GC.Collect();

            StopThread();

            m_hClient = ParentForm.GetClientHandle();
			m_hSerialPort = ParentForm.GetSerialHandle();
            m_hNet = ParentForm.GetNetHandle();


            PCANBasic.Uninitialize(m_hClient);
			m_hSerialPort.Close();
			

            ////Disconnect
            //CanApi2.DisconnectFromNet(m_hClient, m_hNet);
            //// Remove client
            //CanApi2.RemoveClient(m_hClient);
        }

        private void StartFindNodes(object sender, EventArgs e)
        {
            GetNodeInfo();
        }

        private void ClearWindowButton_Click(object sender, EventArgs e)
        {
            FlashtextBox.Text = "";
        }

        private void ReadCANString_Click(object sender, EventArgs e)
        {
            int ObjectIndex = 0, Node = 0;//FileObjectIndex = 0,
            bool SendMessageEnable = true;

            SegmentString.Text = "";
            ShowDone(false);

            if (ChooseMain.Checked)
            {
                if (NodeIdTextBox.Text != "")
                    Node = Int16.Parse(NodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                else
                    SendMessageEnable = false;
            }
            else
            {
                if (SupNodeIdTextBox.Text != "")
                    Node = Int16.Parse(SupNodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                else
                    SendMessageEnable = false;
            }


            if (StringObject.Text != "")
                ObjectIndex = Int32.Parse(StringObject.Text, System.Globalization.NumberStyles.HexNumber);
            else
                SendMessageEnable = false;


            if (SendMessageEnable)
            {
                ParentForm.newMDIChild1.StringData1 = "";
                ParentForm.newMDIChild1.NodeId = Node;
                ParentForm.newMDIChild1.CommandObjectIndex = ObjectIndex;
                ParentForm.newMDIChild1.SegmentWrite = false;
                ParentForm.newMDIChild1.StartSegmentThread();
            }

        }

        private void WriteCANString_Click(object sender, EventArgs e)
        {
            int ObjectIndex = 0, Node = 0;//FileObjectIndex = 0,
            bool SendMessageEnable = true;

            if (ChooseMain.Checked)
            {
                if (NodeIdTextBox.Text != "")
                    Node = Int16.Parse(NodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                else
                    SendMessageEnable = false;
            }
            else
            {
                if (SupNodeIdTextBox.Text != "")
                    Node = Int16.Parse(SupNodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                else
                    SendMessageEnable = false;
            }


            if (StringObject.Text != "")
                ObjectIndex = Int32.Parse(StringObject.Text, System.Globalization.NumberStyles.HexNumber);
            else
                SendMessageEnable = false;

            if (SendMessageEnable)
            {
                ParentForm.newMDIChild1.StringData1 = SegmentString.Text;
                ParentForm.newMDIChild1.NodeId = Node;
                ParentForm.newMDIChild1.CommandObjectIndex = ObjectIndex;
                ParentForm.newMDIChild1.SegmentWrite = true;
                ParentForm.newMDIChild1.StartSegmentThread();
            }

        }

        private void CTFTest1checkBox_CheckedChanged(object sender, EventArgs e)
        {
            if (CTFTest1checkBox.Checked)
                ParentForm.newMDIChild1.CTFTest1 = true;
            else
                ParentForm.newMDIChild1.CTFTest1 = false;
        }

        private void CTFTest2CheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (CTFTest2CheckBox.Checked)
                ParentForm.newMDIChild1.CTFTest2 = true;
            else
                ParentForm.newMDIChild1.CTFTest2 = false;


        }

        private void ReadCANValue_Click(object sender, EventArgs e)
        {
            int ObjectIndex = 0, Node = 0; //DataValue;
            bool SendMessageEnable = true;

            ShowDone(false);
            SegmentString.Text = "";

            if (ChooseMain.Checked)
            {
                if (NodeIdTextBox.Text != "")
                    Node = Int16.Parse(NodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                else
                    SendMessageEnable = false;
            }
            else
            {
                if (SupNodeIdTextBox.Text != "")
                    Node = Int16.Parse(SupNodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                else
                    SendMessageEnable = false;
            }


            if (StringObject.Text != "")
                ObjectIndex = Int32.Parse(StringObject.Text, System.Globalization.NumberStyles.HexNumber);
            else
                SendMessageEnable = false;

            if (SendMessageEnable)
            {
                ParentForm.newMDIChild1.ClientCommandSpecifier = 0x42;
                ParentForm.newMDIChild1.StringData1 = "";
                ParentForm.newMDIChild1.NodeId = Node;
                ParentForm.newMDIChild1.CommandObjectIndex = ObjectIndex;
                ParentForm.newMDIChild1.ValueWrite = false;
                ParentForm.newMDIChild1.StartCANValueThread();
                ParentForm.newMDIChild1.MessageOpDone += new MessageOpHandler(OsFlashDone);
            }

        }

        private void WriteCANValue_Click(object sender, EventArgs e)
        {
            int ObjectIndex = 0, Node = 0, DataValue = 0;
            bool SendMessageEnable = true;

            if (ChooseMain.Checked)
            {
                if (NodeIdTextBox.Text != "")
                    Node = Int16.Parse(NodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                else
                    SendMessageEnable = false;
            }
            else
            {
                if (SupNodeIdTextBox.Text != "")
                    Node = Int16.Parse(SupNodeIdTextBox.Text, System.Globalization.NumberStyles.HexNumber);
                else
                    SendMessageEnable = false;
            }


            if (StringObject.Text != "")
                ObjectIndex = Int32.Parse(StringObject.Text, System.Globalization.NumberStyles.HexNumber);
            else
                SendMessageEnable = false;

            if (SegmentString.Text != "")
                DataValue = Int32.Parse(SegmentString.Text, System.Globalization.NumberStyles.HexNumber);
            else
                SendMessageEnable = false;

            if (EightBit.Checked)
                ParentForm.newMDIChild1.ClientCommandSpecifier = 0x2F;
            else if (SixteenBit.Checked)
                ParentForm.newMDIChild1.ClientCommandSpecifier = 0x2B;
            else if (Thirty2Bit.Checked)
                ParentForm.newMDIChild1.ClientCommandSpecifier = 0x23;

            if (SendMessageEnable)
            {
                ParentForm.newMDIChild1.StringData1 = "";
                ParentForm.newMDIChild1.SDODataValue = DataValue;
                ParentForm.newMDIChild1.NodeId = Node;
                ParentForm.newMDIChild1.CommandObjectIndex = ObjectIndex;
                ParentForm.newMDIChild1.ValueWrite = true;
                ParentForm.newMDIChild1.StartCANValueThread();
            }

        }

        private void StartInhibitButton_Click(object sender, EventArgs e)
        {
            if (!InhibitThreadOn)
                StartInhibit();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            StopInhibit();
        }
        private void SaveNodeInfo()
        {
            ParentForm.SetMainNodeID( NodeIdTextBox.Text);
            ParentForm.SetOSFileName( osFileName.Text + MainFileName.Text);
			MainNodeIDCurrent = NodeIdTextBox.Text;
			UpdateNodeId();
        }
		private void UpdateNodeId()
		{
			TxNodeId = Convert.ToUInt32(MainNodeIDCurrent, 16);
            RxNodeId = TxNodeId + 0x10;
		}

        private void SaveNodeClicked(object sender, EventArgs e)
        {
            SaveNodeInfo();
        }



        private void ProgramProgressBar_Click(object sender, EventArgs e)
        {

        }

        private void MainFileName_TextChanged(object sender, EventArgs e)
        {

        }

        private void OsDonecheckBox_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void FlashFailBox_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void can_rx_lable_Click(object sender, EventArgs e)
        {

        }

        private void osFileName_TextChanged(object sender, EventArgs e)
        {

        }

        private void FlashWindow1319_Load(object sender, EventArgs e)
        {

        }

        private void label16_Click(object sender, EventArgs e)
        {

        }

        private void label16_Click_1(object sender, EventArgs e)
        {

        }

        private void label16_Click_2(object sender, EventArgs e)
        {

        }

        private void buttonReadSN_Click(object sender, EventArgs e)
        {
			UpdateNodeId();			
			kwp_object = 0x001A0088;
			ParentForm.newMDIChild1.StartKWPThread();		
        }

        private void buttonValidate_Click(object sender, EventArgs e)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(serial_number.ToUpper() + secu_secret + mac_address.ToUpper());
            byte[] hash = SHA256Managed.Create().ComputeHash(bytes);
		    string local_key = "";
            for (int i = 0; i < 4; i++)
        	{
        	    local_key += (hash[hash.Length - 4 + i].ToString("X2"));
        	}

			if(local_key.ToUpper() == security_key)
			{
			    StartOsFlash.Enabled = true;
			}
			else
			{
			    StartOsFlash.Enabled = false;
			}
        }

        private void can_tx_textBox_TextChanged(object sender, EventArgs e)
        {

        }

        private void buttonKeyEnter_Click(object sender, EventArgs e)
        {
            security_key = textValidateKey.Text.ToUpper();
            ParentForm.SetSecurityKey(security_key);
        }

        private void label19_Click(object sender, EventArgs e)
        {

        }

		private void sn_TextChanged(object sender, EventArgs e)
        {
            serial_number = textSN.Text.PadLeft(8, '0'); 
			ParentForm.SetSN(textSN.Text.PadLeft(8, '0'));
        }
		private void securityKey_TextChanged(object sender, EventArgs e)
        {
            security_key = textValidateKey.Text.ToUpper();
            ParentForm.SetSecurityKey(security_key);
        }
        private void buttonReadMac_Click(object sender, EventArgs e)
        {
            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
            mac_address = BitConverter.ToString(interfaces[0].GetPhysicalAddress().GetAddressBytes()).Replace("-", "");
            textBoxMac.Text = mac_address;
        }
    }
}
